#include <QPainter>
#include <QMouseEvent>
#include <QDebug>

#include "ChessBoard.h"

// 构造函数
ChessBoard::ChessBoard(QWidget *parent) : QMainWindow(parent)
{
    this->setFixedSize(500, 600);

    // 棋盘初始化
    chessBoardInit();
    // 棋子初始化
    chessManInit();

}

void ChessBoard::chessBoardInit(void)
{
    _origin.setX(50);
    _origin.setY(50);
    _gridSize = 50;
    _chessManR = _gridSize/2 - 2;

    _playerCamp = CAMP_BLACK; // 玩家是黑方
    _currentCamp = CAMP_BLACK; // 黑方先
    _clickedState = NO_CLICK;

    update(); // 刷新绘制
}


// 绘制事件
void ChessBoard::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    uint32_t side = 50;
    
    // 画边框
    painter.drawRect(QRect(_origin.x() - 5, _origin.y() - 5, _gridSize * 8 + 10,_gridSize * 9 + 10));
    painter.setBrush(QColor(239, 235, 231));
    painter.drawRect(QRect(_origin.x() , _origin.y() , _gridSize * 8 ,_gridSize * 9 ));

    // 画横线 row
    for(int i = 1; i < 9; i++)
    {
        painter.drawLine(center(i,0), center(i,8));
    }

    // 画竖线
    for(int i = 1; i < 8; i++)
    {
        painter.drawLine(center(0,i), center(4,i));
        painter.drawLine(center(5,i), center(9,i));
    }

    // 画交叉线
    painter.drawLine(center(0,3), center(2,5));
    painter.drawLine(center(2,3), center(0,5));
    painter.drawLine(center(7,3), center(9,5));
    painter.drawLine(center(9,3), center(7,5));

    // 楚河 汉界
    painter.setFont(QFont("KaiTi",22, QFont::Bold)); // 设置字体和大小
    painter.drawText(QRect(center(4,1), center(5,3)), QStringLiteral("楚河"),QTextOption(Qt::AlignCenter));
    painter.drawText(QRect(center(4,5), center(5,7)), QStringLiteral("汉界"),QTextOption(Qt::AlignCenter));

    for(int i = 0;i < 32;i++)
    {
        drawChessMan(painter,i);
    }

}

// 鼠标点击事件
void ChessBoard::mousePressEvent(QMouseEvent *mevent)
{

}

// 鼠标释放事件
void ChessBoard::mouseReleaseEvent(QMouseEvent *p)
{
    QPoint clickedPos = p->pos(); // 获取释放鼠标时的坐标
    int row,col;
    int id;
    bool clickChess;
    bool win = false;
    
    clickChess = getClickedChessMan(clickedPos,id);

    // 没点到棋子
    if(false == clickChess)
    {
        // 没点击
        if(_clickedState == NO_CLICK)
            return;
        // 之前点过一次
        else if(_clickedState == FIRST_CLICK)
        {
            // 走棋
            // 拿坐标做反向映射出棋盘坐标
            // qDebug() << getChessBoardPos(clickedPos,row,col);
            // qDebug() << row << col;
            if(true == getChessBoardPos(clickedPos,row,col))
            {
                // 判断走棋规则
                if(true == canMove(_firstClickChessId,row,col,32))
                {
                    // 更换坐标
                    _chessMan[_firstClickChessId]._row = row;
                    _chessMan[_firstClickChessId]._col = col;
                    // 取消选中
                    _chessMan[_firstClickChessId]._isClicked = false; 
                    _clickedState = NO_CLICK;
                    // 更换阵营
                    switchcurrentCamp();
                }

            }


        }
    }
    else
    {
        // 之前没点中 + 这次点中棋子
        if(_clickedState == NO_CLICK)
        {
            // 选子
            // 需要和当前阵营一致
            if(_chessMan[id]._camp == _currentCamp) 
            {
                // 该棋子被选中
                _chessMan[id]._isClicked = true;
                _firstClickChessId = id; // 记录第一次选中的ID
                _clickedState = FIRST_CLICK; 
            }
            else
                return; // 不响应

        }
        // 之前点过一次 + 这次点中棋子
        else if(_clickedState == FIRST_CLICK)
        {
            // 点中自己阵营 -> 换选子、取消选子
            if(_chessMan[id]._camp == _currentCamp) 
            {
                // 取消选子
                if(_firstClickChessId == id)
                {
                    _chessMan[_firstClickChessId]._isClicked = false;
                    _clickedState = NO_CLICK;
                }
                // 换选子
                else
                {
                    _chessMan[_firstClickChessId]._isClicked = false;
                    _chessMan[id]._isClicked = true;
                    _firstClickChessId = id; // 更换第一次选中的棋子
                }


            }
            // 点中敌人阵营 -> 吃子
            else
            {
                // 判断走棋规则
                if(true == canMove(_firstClickChessId,_chessMan[id]._row,_chessMan[id]._col,id))
                {
                    // 更换坐标
                    _chessMan[_firstClickChessId]._row = _chessMan[id]._row;
                    _chessMan[_firstClickChessId]._col = _chessMan[id]._col;
                    // 取消选中
                    _chessMan[_firstClickChessId]._isClicked = false; 
                    _clickedState = NO_CLICK;
                    // 敌子阵亡
                    _chessMan[id]._isDead = true;
                    // 判断输赢
                    win = judgeWin();
                    if(win == true)
                    {
                        if(_currentCamp == CAMP_RED)
                            qDebug() << "红方赢";
                        else 
                            qDebug() << "黑方赢";
                        // 棋盘初始化
                        chessBoardInit();
                        // 棋子初始化
                        chessManInit();
                    }
                    else
                    {
                        // 更换阵营
                        switchcurrentCamp();
                    }
 
                }
            }
        }
    }

    update();


}




// 棋子初始化
void ChessBoard::chessManInit(void)
{
    // 棋子初始化
    for(int i = 0; i < 32;i++)
    {
        _chessMan[i].init();
    }
    _chessManIndex = 0;
    // 向棋盘添加棋子
    addChessMan(CAMP_RED,TYPE_CHE,  0, 0);
    addChessMan(CAMP_RED,TYPE_MA,   0, 1);
    addChessMan(CAMP_RED,TYPE_XIANG,0, 2);
    addChessMan(CAMP_RED,TYPE_SHI,  0, 3);
    addChessMan(CAMP_RED,TYPE_JIANG,0, 4);
    addChessMan(CAMP_RED,TYPE_SHI,  0, 5);
    addChessMan(CAMP_RED,TYPE_XIANG,0, 6);
    addChessMan(CAMP_RED,TYPE_MA,   0, 7);
    addChessMan(CAMP_RED,TYPE_CHE,  0, 8);
    addChessMan(CAMP_RED,TYPE_PAO,  2, 1);
    addChessMan(CAMP_RED,TYPE_PAO,  2, 7);
    addChessMan(CAMP_RED,TYPE_BING, 3, 0);
    addChessMan(CAMP_RED,TYPE_BING, 3, 2);
    addChessMan(CAMP_RED,TYPE_BING, 3, 4);
    addChessMan(CAMP_RED,TYPE_BING, 3, 6);
    addChessMan(CAMP_RED,TYPE_BING, 3, 8);

    addChessMan(CAMP_BLACK,TYPE_CHE,  9 - 0, 8 - 0);
    addChessMan(CAMP_BLACK,TYPE_MA,   9 - 0, 8 - 1);
    addChessMan(CAMP_BLACK,TYPE_XIANG,9 - 0, 8 - 2);
    addChessMan(CAMP_BLACK,TYPE_SHI,  9 - 0, 8 - 3);
    addChessMan(CAMP_BLACK,TYPE_JIANG,9 - 0, 8 - 4);
    addChessMan(CAMP_BLACK,TYPE_SHI,  9 - 0, 8 - 5);
    addChessMan(CAMP_BLACK,TYPE_XIANG,9 - 0, 8 - 6);
    addChessMan(CAMP_BLACK,TYPE_MA,   9 - 0, 8 - 7);
    addChessMan(CAMP_BLACK,TYPE_CHE,  9 - 0, 8 - 8);
    addChessMan(CAMP_BLACK,TYPE_PAO,  9 - 2, 8 - 1);
    addChessMan(CAMP_BLACK,TYPE_PAO,  9 - 2, 8 - 7);
    addChessMan(CAMP_BLACK,TYPE_BING, 9 - 3, 8 - 0);
    addChessMan(CAMP_BLACK,TYPE_BING, 9 - 3, 8 - 2);
    addChessMan(CAMP_BLACK,TYPE_BING, 9 - 3, 8 - 4);
    addChessMan(CAMP_BLACK,TYPE_BING, 9 - 3, 8 - 6);
    addChessMan(CAMP_BLACK,TYPE_BING, 9 - 3, 8 - 8);
}

void ChessBoard::addChessMan(ChessCamp_e chessCamp,ChessType_e chessType,int row, int col)
{
    _chessMan[_chessManIndex]._camp = chessCamp; // 阵营
    _chessMan[_chessManIndex]._type = chessType; // 类型
    _chessMan[_chessManIndex]._row = row; 
    _chessMan[_chessManIndex]._col = col;
    _chessMan[_chessManIndex]._isDead = 0; 
    _chessMan[_chessManIndex]._id = _chessManIndex;

    _chessManIndex++;
}


// 绘制棋子
void ChessBoard::drawChessMan(QPainter &painter, int id)
{
    QPoint chessCenter = center(id);
    QRect rect = QRect(chessCenter.x() - _chessManR, chessCenter.y() - _chessManR, 
                        _chessManR*2, _chessManR*2);

    if(_chessMan[id]._isDead == 1)
        return;

    // 绘制圆
    if(_chessMan[id]._isClicked == true)
        painter.setBrush(QBrush(Qt::blue));
    else 
        painter.setBrush(QBrush(QColor(239, 235, 231)));
    painter.drawEllipse(chessCenter,_chessManR,_chessManR);


    // 绘制字
    painter.setRenderHint(QPainter::Antialiasing, true); // 设置渲染
    painter.setFont(QFont("KaiTi",22, QFont::Bold)); // 设置字体和大小
    
    if(_chessMan[id]._camp == CAMP_RED) // 设置颜色 
        painter.setPen(Qt::red);
    else if(_chessMan[id]._camp == CAMP_BLACK)
        painter.setPen(Qt::black);

    painter.drawText(rect, _chessMan[id].getName() ,QTextOption(Qt::AlignCenter));
    
    painter.setPen(Qt::black);

}

// 
bool ChessBoard::canMove(int moveId, int row,int col, int killId)
{
    if(_clickedState == NO_CLICK)
        return false;
    switch (_chessMan[moveId]._type)
    {
        case TYPE_JIANG:
            return canMoveJiang(moveId,row,col,killId);
        case TYPE_SHI:
            return canMoveShi(moveId,row,col,killId);
        case TYPE_XIANG:
            return canMoveXiang(moveId,row,col,killId);
        case TYPE_MA:
            return canMoveMa(moveId,row,col,killId);
        case TYPE_CHE:
            return canMoveChe(moveId,row,col,killId);
        case TYPE_PAO:
            return canMovePao(moveId,row,col,killId);
        case TYPE_BING:
            return canMoveBing(moveId,row,col,killId);
        default:
           return false; 
    }

}

// 将
bool ChessBoard::canMoveJiang(int moveId,int row,int col, int killId)
{
    bool canMove = false;
    int dRow,dCol;
    /*
    走棋规则
    1、每次走一步
    2、不能走斜线
    2、不出九宫
     */
    // 上面的棋子
    if(_chessMan[moveId]._camp != _playerCamp)
    {
        if(row >= 0 && row <= 2 && col >= 3 && col <= 5)
        {
            canMove = true;
        }
        
    }
    // 下面的棋子
    else
    {
        if(row >= 7 && row <= 9 && col >= 3 && col <= 5)
        {
            canMove = true;
        }
    }

    if(canMove == true)
    {
        dRow = _chessMan[moveId]._row - row;
        dCol = _chessMan[moveId]._col - col;
        // 只能走一步
        if( dRow * dRow + dCol * dCol != 1)
        {
            canMove = false;
        }
    }

    // 没有吃子
    if(killId >= 32)
        return canMove;
    /*
    吃子规则
    1、九宫格里随便吃
     */
    return canMove;



}
// 士 
bool ChessBoard::canMoveShi(int moveId,int row,int col, int killId)
{
    bool canMove = false;
    int dRow,dCol;
    /*
    走棋规则
    1、每次走一步
    2、只能斜着走
    2、不出九宫
     */
    // 限制九宫格
    // 上面的棋子
    if(_chessMan[moveId]._camp != _playerCamp)
    {
        if(row >= 0 && row <= 2 && col >= 3 && col <= 5)
        {
            canMove = true;
        }
        
    }
    // 下面的棋子
    else
    {
        if(row >= 7 && row <= 9 && col >= 3 && col <= 5)
        {
            canMove = true;
        }
    }

    if(canMove == true)
    {
        dRow = _chessMan[moveId]._row - row;
        dCol = _chessMan[moveId]._col - col;
        // 只能斜着走
        if( dRow * dRow + dCol * dCol != 2)
        {
            canMove = false;
        }
    }
    // 没有吃子
    if(killId >= 32)
        return canMove;
    /*
    吃子规则
    1、九宫格里随便吃
     */
    return canMove;

}
// 相
bool ChessBoard::canMoveXiang(int moveId,int row,int col, int killId)
{
    bool canMove = false;
    int dRow,dCol;
    int jRow,jCol;
    /*
    走棋规则
    1、走田
    2、田中有子不能走
    3、不能过河
     */
    // 上面的棋子
    if(_chessMan[moveId]._camp != _playerCamp)
    {
        if(row <= 4)
        {
            canMove = true;
        }
        
    }
    // 下面的棋子
    else
    {
        if(row >= 5)
        {
            canMove = true;
        }
    }

    if(canMove == true)
    {
        dRow = _chessMan[moveId]._row - row;
        dCol = _chessMan[moveId]._col - col;
        // 走田
        if( dRow * dRow + dCol * dCol != 8)
        {
            canMove = false;
        }
        else
        {
            jRow = _chessMan[moveId]._row - dRow/2;
            jCol = _chessMan[moveId]._col - dCol/2;
            // 判断田中是否有子
            if(true == judgeChessManInPos(jRow,jCol))
            {
                canMove = false;
            }
        }
    }
    // 没有吃子
    if(killId >= 32)
        return canMove;
    /*
    吃子规则
    1、满足走步随便吃
     */
    return canMove;


}
// 马   
bool ChessBoard::canMoveMa(int moveId,int row,int col, int killId)
{
    bool canMove = false;
    int dRow,dCol;
    int jRow,jCol;
    /*
    走棋规则
    1、走日
    2、想跳的方向有个棋子挨着就不能跳
     */
    // 上面的棋子
    if(_chessMan[moveId]._camp != _playerCamp)
    {
        canMove = true;
    }
    // 下面的棋子
    else
    {
        canMove = true;
    }

    if(canMove == true)
    {
        dRow = _chessMan[moveId]._row - row;
        dCol = _chessMan[moveId]._col - col;
        // 走田
        if( dRow * dRow + dCol * dCol != 5)
        {
            canMove = false;
        }
        else
        {
            if(dRow * dRow == 4)
            {
                jRow = _chessMan[moveId]._row - dRow/2;
                jCol = _chessMan[moveId]._col;
            }
            else if(dCol * dCol == 4)
            {
                jRow = _chessMan[moveId]._row;
                jCol = _chessMan[moveId]._col - dCol/2;
            }
            
            // 想跳的方向有个棋子挨着
            if(true == judgeChessManInPos(jRow, jCol))
            {
                canMove = false;
            }
        }
    }
    // 没有吃子
    if(killId >= 32)
        return canMove;
    /*
    吃子规则
    1、满足走步随便吃
     */
    return canMove;
}
// 车
bool ChessBoard::canMoveChe(int moveId,int row,int col, int killId)
{
    bool canMove = false;
    int dRow,dCol;
    int jRow,jCol;
    int i;
    /*
    走棋规则
    1、直线走，只要无子阻拦，步数不受限制
     */
    // 上面的棋子
    if(_chessMan[moveId]._camp != _playerCamp)
    {
        canMove = true;
    }
    // 下面的棋子
    else
    {
        canMove = true;
    }

    if(canMove == true)
    {
        dRow = _chessMan[moveId]._row - row;
        dCol = _chessMan[moveId]._col - col;

        if( dRow != 0 && dCol != 0)
        {
            canMove = false;
        }
        else
        {
            // 竖方向
            if(dRow != 0)
            {
                if(dRow > 0)
                {
                    for(i = 1;i < dRow;i++)
                    {
                        jRow = _chessMan[moveId]._row - i;
                        jCol = _chessMan[moveId]._col;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            canMove = false;
                        }
                    }
                }
                else if(dRow < 0)
                {
                    for(i = 1;i < -dRow;i++)
                    {
                        jRow = _chessMan[moveId]._row + i;
                        jCol = _chessMan[moveId]._col;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            canMove = false;
                        }
                    }
                }

            }
            // 横方向
            else if(dCol != 0)
            {
                if(dCol > 0)
                {
                    for(i = 1;i < dCol;i++)
                    {
                        jRow = _chessMan[moveId]._row;
                        jCol = _chessMan[moveId]._col - i;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            canMove = false;
                        }
                    }
                }
                else if(dCol < 0)
                {
                    for(i = 1;i < -dCol;i++)
                    {
                        jRow = _chessMan[moveId]._row;
                        jCol = _chessMan[moveId]._col + i;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            canMove = false;
                        }
                    }
                }
            }
                

        }
    }
    // 没有吃子
    if(killId >= 32)
        return canMove;
    /*
    吃子规则
    1、满足走步随便吃
     */
    return canMove;
}  
// 炮   
bool ChessBoard::canMovePao(int moveId,int row,int col, int killId)
{
    bool canMove = false;
    int dRow,dCol;
    int jRow,jCol;
    int i;
    int cnt = 0; // 子计数
    /*
    走棋规则
    1、不吃子的时候，移动和车一样;
    2、吃子时，必须越一子吃
     */
    // 上面的棋子
    if(_chessMan[moveId]._camp != _playerCamp)
    {
        canMove = true;
    }
    // 下面的棋子
    else
    {
        canMove = true;
    }

    if(canMove == true)
    {
        dRow = _chessMan[moveId]._row - row;
        dCol = _chessMan[moveId]._col - col;
        
        if( dRow != 0 && dCol != 0)
        {
            canMove = false;
        }
        else
        {
            // 竖方向
            if(dRow != 0)
            {
                if(dRow > 0)
                {
                    for(i = 1;i < dRow;i++)
                    {
                        jRow = _chessMan[moveId]._row - i;
                        jCol = _chessMan[moveId]._col;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            cnt++;
                            canMove = false;
                        }
                    }
                }
                else if(dRow < 0)
                {
                    for(i = 1;i < -dRow;i++)
                    {
                        jRow = _chessMan[moveId]._row + i;
                        jCol = _chessMan[moveId]._col;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            cnt++;
                            canMove = false;
                        }
                    }
                }

            }
            // 横方向
            else if(dCol != 0)
            {
                if(dCol > 0)
                {
                    for(i = 1;i < dCol;i++)
                    {
                        jRow = _chessMan[moveId]._row;
                        jCol = _chessMan[moveId]._col - i;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            cnt++;
                            canMove = false;
                        }
                    }
                }
                else if(dCol < 0)
                {
                    for(i = 1;i < -dCol;i++)
                    {
                        jRow = _chessMan[moveId]._row;
                        jCol = _chessMan[moveId]._col + i;
                        if(true == judgeChessManInPos(jRow,jCol))
                        {
                            cnt++;
                            canMove = false;
                        }
                    }
                }
            }
        }
    }
    // 没有吃子
    if(killId >= 32)
        return canMove;
    /*
    吃子规则
    1、必须越一子吃
     */
    if(cnt != 1)
    {
        canMove = false;
    }
    else
    {
        canMove = true;
    }
    return canMove;
} 
// 兵   
bool ChessBoard::canMoveBing(int moveId,int row,int col, int killId)
{
    bool canMove = false;
    int dRow,dCol;

    int crossRiver = 0; // 过河
    /*
    走棋规则
    1、未过河前只能向前走一步，过河后除不能后退外，还可以左右，每次一步
     */
    // 上面的棋子
    if(_chessMan[moveId]._camp != _playerCamp)
    {
        canMove = true;
        // 不允许后退 (无论有没过河)
        if(_chessMan[moveId]._row > row)
        {
            canMove = false;
        }
        // 判断是否过河
        if(_chessMan[moveId]._row > 4)
        {
            crossRiver = 1;
        }

    }
    // 下面的棋子
    else
    {
        canMove = true;
        // 不允许后退 (无论有没过河)
        if(_chessMan[moveId]._row < row)
        {
            canMove = false;
        }
        // 判断是否过河
        if(_chessMan[moveId]._row < 5)
        {
            crossRiver = 1;
        }

    }

    // 没过河
    if(!crossRiver)
    {
        if(_chessMan[moveId]._col != col)
        {
            canMove = false;
        }
    }

    // 没有吃子
    if(killId >= 32)
        return canMove;
    /*
    吃子规则
    1、满足走步随便吃
     */
    return canMove;
}  

// 判断赢
bool ChessBoard::judgeWin(void)
{
    for(int i = 0;i < 32;i++)
    {
        if(_chessMan[i]._isDead == true)
        {
            if(_chessMan[i]._type == TYPE_JIANG)
            {
                return true;
            }
        }        
    }
    return false;
}

// 判断棋子是否在位置
bool ChessBoard::judgeChessManInPos(int row,int col)
{
    for(int i = 0;i < 32;i++)
    {
        // 判断棋子是否死亡
        if(_chessMan[i]._isDead == 1)
            continue;
        if(row == _chessMan[i]._row && col == _chessMan[i]._col)
        {
            return true;
        }
    }
    return false;
}

bool ChessBoard::getClickedChessMan(QPoint clickPos,int &id)
{   
    QPoint chessPos;
    int dx,dy;
    // 遍历所有棋子
    for(int i = 0;i < 32;i++)
    {
        // 判断棋子是否死亡
        if(_chessMan[i]._isDead == 1)
            continue;
        chessPos = center(i);
        dx = chessPos.x() - clickPos.x();
        dy = chessPos.y() - clickPos.y();
        // 判断棋子和点击点的距离
        if(dx*dx + dy*dy < _chessManR*_chessManR)
        {  
            id = i;
            // 选中
            return true;
        }
    }

    return false;


}


// 由棋盘坐标获取绝对坐标
QPoint ChessBoard::center(int row,int col)
{
    QPoint ret;
    // 基础坐标叠加格子
    // X对应col Y对应row
    ret.setX(_origin.x() + col * _gridSize);
    ret.setY(_origin.y() + row * _gridSize);
    return ret;

}

// 由棋子ID获取绝对坐标
QPoint ChessBoard::center(int id)
{
    return center(_chessMan[id]._row,_chessMan[id]._col);
}

bool ChessBoard::getChessBoardPos(QPoint pos,int &row,int &col)
{
    int x,y;
    if(pos.x() < _origin.x() - (_gridSize / 2) || pos.y() < _origin.y() - (_gridSize / 2))
        return false;
    if(pos.x() > _origin.x() + _gridSize * 8 + (_gridSize / 2) || pos.y() > _origin.y() + _gridSize * 9 + (_gridSize / 2))
        return false;

    y = pos.y() - _origin.y();
    row = y / _gridSize;
    if((y % _gridSize) > (_gridSize / 2))
        row = row + 1;

    x = pos.x() - _origin.x();
    col = x / _gridSize;
    if((x % _gridSize) > (_gridSize / 2))
        col = col + 1;

    return true;


}